package handler

import (
	"context"
	"crypto/hmac"
	"encoding/hex"
	"fmt"
	"golang.org/x/crypto/ripemd160"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
	"google.golang.org/protobuf/types/known/emptypb"
	"gorm.io/gorm"
	"project_srvs/user_srv/global"
	"project_srvs/user_srv/model"
	"project_srvs/user_srv/proto/user"
	"project_srvs/user_srv/utils"
	"time"
)

type UserServer struct {
	user.UnimplementedUserServer
}

func ModelToResponse(userModel model.Users) *user.UserInfoResponse {
	//在grpc的message中字段有默认值，你不能随便赋值nil进去，容易出错
	//这里要搞清， 哪些字段是有默认值
	userInfoRsp := &user.UserInfoResponse{
		Id:            userModel.ID,
		NickName:      userModel.NickName,
		HeadImgUrl:    userModel.HeadImgUrl,
		Constellation: userModel.Constellation,
		Sex:           userModel.Sex,
		Phone:         userModel.Phone,
		BirthDay:      userModel.Birthday,
		ZhuxiaoTime:   userModel.ZhuxiaoTime,
		Status:        userModel.Status,
		CreatedAt:     userModel.CreatedAt,
		City:          userModel.City,
		IsSign:        userModel.IsSign,
		IsAccept:      userModel.IsAccept,
		Salt:          userModel.Salt,
		Pass:          userModel.Pass,
		RyUid:         userModel.RyUid,
		RyToken:       userModel.RyToken,
		IdNo:          userModel.IdNo,
		IsIdCard:      userModel.IsIdCard,
		MiZuan:        userModel.MiZuan,
		MiBi:          userModel.MiBi,
		SqDisable:     userModel.SqDisable,
		SjDisable:     userModel.SjDisable,
	}
	//if userModel.Birthday != "" {
	//	userInfoRsp.BirthDay = uint64(userModel.Birthday.Unix())
	//}
	return userInfoRsp
}

func Paginate(page, pageSize int) func(db *gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {
		if page == 0 {
			page = 1
		}

		switch {
		case pageSize > 100:
			pageSize = 100
		case pageSize <= 0:
			pageSize = 10
		}

		offset := (page - 1) * pageSize
		return db.Offset(offset).Limit(pageSize)
	}
}

func (s *UserServer) GetUserList(ctx context.Context, in *user.PageInfo) (*user.UserListResponse, error) {
	var users []model.Users
	result := global.DB.Find(&users)
	if result.Error != nil {
		return nil, result.Error
	}
	fmt.Println("用户列表")
	resp := &user.UserListResponse{}
	resp.Total = int32(result.RowsAffected)

	global.DB.Scopes(Paginate(int(in.Pn), int(in.PSize))).Find(&users)
	for _, userRow := range users {
		userInfoResp := ModelToResponse(userRow)
		resp.Data = append(resp.Data, userInfoResp)
	}

	return resp, nil
}

func (s *UserServer) GetUserByMobile(ctx context.Context, in *user.PhoneRequest) (*user.UserInfoResponse, error) {
	var userModel model.Users
	result := global.DB.Where(&model.Users{Phone: in.Phone}).First(&userModel)
	if result.RowsAffected == 0 {
		return nil, status.Errorf(codes.NotFound, "用户不存在")
	}
	if result.Error != nil {
		return nil, result.Error
	}

	userRespInfo := ModelToResponse(userModel)
	return userRespInfo, nil
}

func (s *UserServer) GetUserById(ctx context.Context, in *user.IdRequest) (*user.UserInfoResponse, error) {
	// 通过Id 查询用户
	var userModel model.Users
	result := global.DB.First(&userModel, in.Id)
	if result.RowsAffected == 0 {
		return nil, status.Errorf(codes.NotFound, "用户不存在")
	}
	if result.Error != nil {
		return nil, result.Error
	}

	userRespInfo := ModelToResponse(userModel)
	return userRespInfo, nil
}

func (s *UserServer) CreateUser(ctx context.Context, in *user.CreateUserInfo) (*user.UserInfoResponse, error) {
	var userModel model.Users
	result := global.DB.Where(&model.Users{Phone: in.Phone}).First(&userModel)
	if result.RowsAffected == 1 {
		return nil, status.Errorf(codes.AlreadyExists, "用户已存在")
	}

	userModel.Phone = in.Phone
	userModel.NickName = in.NickName
	userModel.Sex = in.Sex
	if in.BirthDay != 0 {
		birthday := time.Unix(int64(in.BirthDay), 0)
		// 格式化时间，保留年月日部分
		formattedBirthday := birthday.Format("2006-01-02")
		userModel.Birthday = formattedBirthday
	}
	userModel.Constellation = in.Constellation
	userModel.HeadImgUrl = in.HeadImgUrl
	userModel.LoginIp = in.LoginIp
	userModel.System = in.System
	userModel.Channel = in.Channel
	userModel.Appid = in.Appid
	userModel.Channel = in.Channel

	salt := utils.GetRandomStr(3, true)
	userModel.Salt = salt
	passwordStr := utils.GetRandomStr(10, true)
	encryptedPassword := utils.GetEncryptPassword(passwordStr, salt)
	userModel.Pass = encryptedPassword
	result = global.DB.Create(&userModel)
	if result.Error != nil {
		return nil, status.Errorf(codes.Internal, result.Error.Error())
	}
	userInfoResp := ModelToResponse(userModel)
	return userInfoResp, nil
}

func (s *UserServer) UpdateUser(ctx context.Context, in *user.UpdateUserInfo) (*emptypb.Empty, error) {
	var userModel model.Users
	result := global.DB.First(&userModel, in.Id)
	if result.RowsAffected == 0 {
		return nil, status.Errorf(codes.NotFound, "用户不存在")
	}

	birthday := time.Unix(int64(in.BirthDay), 0)
	// 格式化时间，保留年月日部分
	formattedBirthday := birthday.Format("2006-01-02")
	userModel.Birthday = formattedBirthday
	userModel.NickName = in.NickName
	userModel.Sex = in.Sex

	result = global.DB.Save(&userModel)
	if result.Error != nil {
		return nil, status.Errorf(codes.Internal, result.Error.Error())
	}

	return &emptypb.Empty{}, nil
}

func (s *UserServer) SetUserPassword(ctx context.Context, in *user.SetUserPassInfo) (*emptypb.Empty, error) {
	var userModel model.Users
	result := global.DB.First(&userModel, in.Id)
	if result.RowsAffected == 0 {
		return nil, status.Errorf(codes.NotFound, "用户不存在")
	}

	salt := utils.GetRandomStr(3, true)
	userModel.Salt = salt
	encryptedPassword := utils.GetEncryptPassword(in.Pass, salt)
	userModel.Pass = encryptedPassword

	result = global.DB.Save(&userModel)
	if result.Error != nil {
		return nil, status.Errorf(codes.Internal, result.Error.Error())
	}

	return &emptypb.Empty{}, nil
}

func (s *UserServer) GetUserToken(ctx context.Context, in *user.GetUserTokenInfo) (*user.UserTokenResponse, error) {
	var userTokenModel model.UserToken
	uKey := global.ServerConfig.UserTokenKey
	uTokenNew := hashHMACRIPEMD160(in.Token, []byte(uKey))

	// 查询Token是否存在
	uTokenResult := global.DB.Where(&model.UserToken{Token: uTokenNew}).First(&userTokenModel)
	if uTokenResult.Error != nil {
		// 如果查询出错，返回错误
		return nil, uTokenResult.Error
	}

	// 如果Token存在且有效
	if uTokenResult.RowsAffected != 0 {
		if userTokenModel.ExpireTime == 0 || userTokenModel.ExpireTime > time.Now().Unix() {
			// Token有效，返回相关信息
			return &user.UserTokenResponse{
				Token:      uTokenNew,
				UserId:     userTokenModel.UserId,
				ExpireTime: userTokenModel.ExpireTime,
				ExpireIn:   getExpiredIn(userTokenModel.ExpireTime),
			}, nil
		} else {
			// Token已过期，删除Token记录
			deleteResult := global.DB.Where(&model.UserToken{Token: uTokenNew}).Delete(&userTokenModel)
			if deleteResult.Error != nil {
				return nil, deleteResult.Error
			}
		}
	}

	// 返回用户的Token信息
	return nil, status.Errorf(codes.NotFound, "Token has expired")
}

func (s *UserServer) CheckPassWord(ctx context.Context, in *user.PasswordCheckInfo) (*user.CheckResponse, error) {
	encryptedPassword := utils.GetEncryptPassword(in.Password, in.Salt)
	if encryptedPassword != in.EncryptedPassword {
		return &user.CheckResponse{Success: false}, nil
	}
	return &user.CheckResponse{Success: true}, nil
}

func hashHMACRIPEMD160(data string, key []byte) string {
	// 使用 HMAC-RIPEMD160
	h := hmac.New(ripemd160.New, key)
	h.Write([]byte(data))
	hash := h.Sum(nil)
	return hex.EncodeToString(hash) // 转换为十六进制字符串
}

// getExpiredIn 计算剩余的过期时间
func getExpiredIn(expireTime int64) int64 {
	if expireTime == 0 {
		return 365 * 86400
	}
	currentTime := time.Now().Unix() // 获取当前时间的 Unix 时间戳
	return maxInt64(0, expireTime-currentTime)
}

// max 返回两个整数中的较大值
func maxInt64(a, b int64) int64 {
	if a > b {
		return a
	}
	return b
}
